#include <inctypes.h>
#include <incctrls.h>

/* ============= 结构体初始化相关 ================ */

/*********************************************************************************
 * 
 * fsobj_t_init - 初始化 文件系统对象 (面向目录/文件) 结构体
 * 
 * DESCRIPTION
 */

static void fsobj_t_init
    (
    fsobj_t * initp
    )
    {
    uint_t i;

    initp->status = 0;
    initp->type   = FS_OBJTYPE_NUL;  /* 文件系统对象类型初始化为 NUL */
    initp->blkidx = 0;               /* 指向文件数据管理头的块号 (逻辑块块号) 初始化为 0 */

    /* 名字空间初始化为空 */

    for (i = 0; i < FSOBJ_NM_MAX; i++)
        {
        initp->name[i] = 0;
        }

    return;
    }

/*********************************************************************************
 * 
 * fsobjlogblk_t_init - 初始化  文件系统对象逻辑块 结构体
 * 
 * DESCRIPTION
 */

static void fsobjlogblk_t_init
    (
    fsobjlogblk_t * initp
    )
    {
    initp->blkstart = 0;    /* 起始逻辑块序号 */
    initp->blknbr   = 0;    /* 连续使用逻辑块个数 */

    return;
    }

/*********************************************************************************
 * 
 * fsobjmh_t_init - 初始化  文件系统对象管理头 结构体
 * 
 * DESCRIPTION
 */

static void fsobjmh_t_init
    (
    fsobjmh_t * initp
    )
    {
    uint_t i;
    
    initp->flag            = 0;              /* 标志 */
    initp->status          = 0;              /* 状态 */
    initp->type            = FS_OBJTYPE_NUL; /* 类型默认为 NUL */
    initp->sfblkidx        = 0;              /* 对象管理头自身所在的逻辑块序号 */
    initp->access          = 0;              /* 访问权限 */
    initp->blknbr          = 0;              /* 对象占逻辑储存块个数 */
    initp->size            = 0;              /* 对象大小 */
    initp->firstblkoffset  = 512;  /* 文件数据在所在第一个逻辑块中的偏移 (前512B保存fsobjmh_t结构体) */
    initp->endblkoffset    = 0;    /* 文件数据在最后块逻辑块中的偏移 */
    initp->curwrtblkidx    = 0;    /* 文件数据当前将要写入的逻辑块 */
    initp->curwrtblkoffset = 0;    /* 文件数据在将要写入的逻辑块中的偏移 */

    /* 时间初始化 */

//    initp->newtime = ;
//    initp->acstime = ;
//    initp->modtime = ;

    /* 初始化该文件所占逻辑块的起始信息和连续个数信息 */

    for (i = 0; i < FSBLKS_NBR_MAX; i++)
        {
        fsobjlogblk_t_init (&initp->logblk[i]);
        }

    /* 默认该文件无扩展 逻辑块管理数组 */
    
    initp->linkprevmh = NULL;
    initp->linknextmh = NULL;

    return;
    }

/*********************************************************************************
 * 
 * fssupblk_t_init - 初始化  初始化超级块数据结构 结构体
 * 
 * DESCRIPTION
 */

static void fssupblk_t_init
    (
    fssupblk_t * initp
    )
    {
    spinlock_init (&initp->lock);

    /* 初始化 flag 和 status */

    initp->flag   = 0;
    initp->status = 0;

    /* 文件标志 (默认 0x210816) */

    initp->magic = 0x210816;

    /* 设置文件系统版本 */

    initp->majver = FSVER_MAJ;
    initp->subver = FSVER_SUB;

    /* 超级块结构体本身大小 */

    initp->strucsz = sizeof (fssupblk_t);

    /* 逻辑块大小 (4KB)  */

    initp->logblksz = FSLOGBLK_SZ;

    /* 
     * 超级块从第0个逻辑块开始, 占用1个逻辑块
     * 位图块从第1个逻辑块开始, 占用1个逻辑块 
     */

    initp->supblkstart = 0;
    initp->supblknbr   = 1;
    initp->bmpblkstart = 1;
    initp->bmpblknbr   = 1;

    /* 初始化文件系统总的逻辑块个数 */

    initp->fsallblknbr = 0;

    /* 初始化根目录 */

    fsobj_t_init (&initp->rootdir);

    return;
    }

/*********************************************************************************
 * 
 * fsemsto_t_init - 初始化  虚拟存储介质数据结构体 结构体
 * 
 * DESCRIPTION
 */

static void fsemsto_t_init 
    (
    fsemsto_t * initp
    )
    {
    spinlock_init (&initp->lock); /* 初始化自旋锁 */
    list_init (&initp->list);         /* 初始化链表 */

    initp->flag      = 0;    /* 标志 */
    initp->status    = 0;    /* 状态 */
    initp->addrstart = NULL; /* 开始地址 */
    initp->size      = 0;    /* 存储介质总大小 */

    return;
    }

/* =================== 辅助函数 =================== */

/****** (虚拟) 存储介质相关 (创建) ******/

/*********************************************************************************
 * 
 * fs_create_fsemsto_mmblk - 分配虚拟存储介质(内存块)
 * 
 * DESCRIPTION
 */

static drvstus_t fs_create_fsemsto_mmblk
    (
    device_t * devp,
    size_t     blksz
    )
    {

    addr_t      blkp;
    fsemsto_t * emstop;

    /* 分配模拟存储介质的内存空间 (4MB) */

    blkp = krl_mem_new (blksz);

    if (blkp == NULL)
        {
        return ERROR;   /* 分配内存失败 */
        }

    /* 分配 fsemsto_t 实例变量 */

    emstop = (fsemsto_t *) krl_mem_new (sizeof (fsemsto_t));

    if (emstop == NULL)
        {
        return ERROR;    /* 分配失败 */
        }

    /* 初始化 fsemsto_t 结构 */

    fsemsto_t_init (emstop);

    emstop->addrstart = (void *) blkp;
    emstop->size      = blksz;

    /* 把 fsemsto_t 结构体放到 device_t 拓展成员域中 */

    devp->exp_data = (void *) emstop; 

    /* 返回成功 */

    return OK;
    }

/****** 缓冲区操作 (简历/释放) ******/

/*********************************************************************************
 * 
 * fs_new_buf - 分配缓冲区
 * 
 * DESCRIPTION
 */

static buf_t fs_new_buf
    (
    size_t size
    )
    {
    buf_t addr;

    /* 申请缓冲区内存 */

    addr = (buf_t) krl_mem_new (size);

    return addr;
    }

/* 释放缓冲区 */

static bool_t fs_delete_buf
    (
    buf_t  buf,
    size_t size
    )
    {
    bool_t retstus;

    /* 释放缓冲区内存 */

    retstus = krl_mem_delete ((addr_t) buf, size);

    if (retstus == FALSE)
        {
        krl_system_die ("fs_delete_buf err\r\n");
        return FALSE;
        }

    /* 释放成功 */

    return TRUE;
    }

/****** 虚拟存储介质相关 (逻辑存储块 返回地址/个数, 写入/读取) ******/

/*********************************************************************************
 * 
 * fs_get_device_expdata - 返回设备扩展数据结构
 * 
 * DESCRIPTION
 */

static fsemsto_t * fs_get_device_expdata
    (
    device_t * devp
    )
    {
    fsemsto_t * emstop;

    emstop = (fsemsto_t *) devp->exp_data;

    return emstop;
    }

/*********************************************************************************
 * 
 * fs_get_fsemsto_blkaddr - 根据逻辑块序号返回存储介质的逻辑块地址
 * 
 * DESCRIPTION
 */

static void * fs_get_fsemsto_blkaddr
    (
    device_t * devp,
    uint_t     blkidx
    )
    {
    fsemsto_t * emstop;
    void *      blkp;
        
    /* 获得设备扩展数据结构 */

    emstop = fs_get_device_expdata (devp);

    /* 逻辑块号乘以逻辑块大小加上开始地址 (用于模拟存储介质的内存空间的开始地址) */

    blkp = emstop->addrstart + (blkidx * FSLOGBLK_SZ);

    /* 判断 逻辑块的地址是否在内存块地址之间 */

    if (blkp >= (void *) ((size_t) emstop->addrstart + emstop->size))
        {
        return NULL; /* 不在区间之内 */ 
        }

    /* 返回块地址 */

    return blkp;
    }

/*********************************************************************************
 * 
 * fs_get_fsemsto_blknbr - 返回存储介质的逻辑存储块个数
 * 
 * DESCRIPTION
 */

static uint_t fs_get_fsemsto_blknbr
    (
    device_t * devp
    )
    {
    fsemsto_t * emstop;
    uint_t      blknbr;

    /* 返回设备的扩展数据 */

    emstop = fs_get_device_expdata (devp);

    /* 计算逻辑存储块的个数 */

    blknbr = (uint_t) (emstop->size / FSLOGBLK_SZ);

    return blknbr;
    }

/*********************************************************************************
 * 
 * fs_write_to_fsemsto - 把缓冲区中的内容 写入到 存储介质的的某个 逻辑存储块 中
 * 
 * DESCRIPTION
 */

static drvstus_t fs_write_to_fsemsto
    (
    device_t * devp,
    buf_t      wraddr,
    uint_t     blkidx
    )
    {

    void * blkp;

    /* 返回存储介质中第 blkidx 块的逻辑存储块存储地址 */

    blkp = fs_get_fsemsto_blkaddr (devp, blkidx);

    if (blkp == NULL)
        {
        return ERROR;  /* 获取存储块地址失败 */
        }

    /* 复制数据到逻辑存储块中 */

    krl_memncpy (wraddr, blkp, FSLOGBLK_SZ);

    return OK;
    }

/*********************************************************************************
 * 
 * fs_read_from_fsemsto - 把 存储介质的的某个 逻辑存储块 中的内容 读取到 缓冲区 中
 * 
 * DESCRIPTION
 */

static drvstus_t fs_read_from_fsemsto
    (
    device_t * devp,
    buf_t      rdaddr,
    uint_t     blkidx
    )
    {
    void * blkp;

    /* 获取逻辑存储块地址 */

    blkp = fs_get_fsemsto_blkaddr (devp, blkidx);

    if (blkp == NULL)
        {
        return ERROR; /* 获取失败 */
        }

    /* 把逻辑存储块中的数据复制到缓冲区 */

    krl_memncpy (rdaddr, blkp, FSLOGBLK_SZ);

    return OK;
    }

/****** 超级块相关 (创建/获取/释放) ******/

/*********************************************************************************
 * 
 * fs_create_superblk - 创建超级块
 * 
 * DESCRIPTION
 */

static bool_t fs_create_superblk
    (
    device_t * devp
    )
    {
    buf_t        buf;
    bool_t       retstus;
    fssupblk_t * sblkp;

    /* 分配 FSLOGBLK_SZ 大小的缓冲区  */

    buf = fs_new_buf (FSLOGBLK_SZ);

    if (buf == NULL)
        {
        return FALSE; /* 分配缓冲区失败 */
        }

    /* 缓冲区清0 */

    krl_memset (buf, 0, FSLOGBLK_SZ);

    /* 创建 fssupblk_t 指针指向该缓冲区 */

    sblkp = (fssupblk_t *) buf;

    /* 初始化超级块 */

    fssupblk_t_init (sblkp);
    
    /* 获取存储介质的逻辑存储块块数并存储到超级块中 */

    sblkp->fsallblknbr = fs_get_fsemsto_blknbr (devp);

    /* 把缓冲区的数据 (即超级块) 写入到存储介质的第0个逻辑存储块中 */

    if (fs_write_to_fsemsto (devp, buf, 0) == ERROR)
        {
        retstus = FALSE;
        goto return_step; /* 写入失败 */
        }

    /* 写入成功 */

    retstus = TRUE;

return_step:

    /* 释放缓冲区 */

    fs_delete_buf (buf, FSLOGBLK_SZ);

    return retstus;
    }

/*********************************************************************************
 * 
 * fs_get_superblk - 获取超级块
 * 
 * DESCRIPTION
 */

static fssupblk_t * fs_get_superblk
    (
    device_t * devp
    )
    {
    buf_t     buf;

    /* 分配 4KB 大小的缓冲区 */

    buf = (buf_t) krl_mem_new (FSLOGBLK_SZ);

    if (buf == NULL)
        {
        return NULL; /* 分配失败 */
        }

    /* 缓冲区清0 */

    krl_memset (buf, 0, FSLOGBLK_SZ);

    /* 把第 0 个逻辑存储块读取到缓冲区中 */

    if (fs_read_from_fsemsto (devp, buf, 0) == ERROR)
        {
        fs_delete_buf (buf, FSLOGBLK_SZ);
        return NULL;                        /* 读取失败 */
        }

    /* 返回超级块数据结构的地址, 即缓冲区首地址 */

    return ((fssupblk_t *) buf);
    }

/*********************************************************************************
 * 
 * fs_release_superblk - 释放超级块
 * 
 * DESCRIPTION
 */

static bool_t fs_release_superblk
    (
    device_t *   devp,
    fssupblk_t * sblkp
    )
    {

    /* 将缓冲区中的内容 回写到 超级块所在的 逻辑存储块 */

    if (fs_write_to_fsemsto (devp, (buf_t) sblkp, 0) == ERROR)
        {
        krl_system_die ("fs_release_superblk err\r\n");
        return FALSE;
        }

    /* 释放成功 释放缓冲区 */

    fs_delete_buf ((buf_t) sblkp, FSLOGBLK_SZ);

    return TRUE;
    }

/****** 位图块相关 (创建) ******/

/*********************************************************************************
 * 
 * fs_create_bitmap - 建立位图块
 * 
 * DESCRIPTION
 */

static bool_t fs_create_bitmap
    (
    device_t * devp
    )
    {
    bool_t       retstus = FALSE;
    fssupblk_t * sblkp;
    buf_t        buf;
    uint_t       bmpblkstart;
    uint_t       allblknbr;
    u8_t *       bmu8p;
    uint_t       i;

    /* 获取超级块 */

    sblkp = fs_get_superblk (devp);

    if (sblkp == NULL)
        {
        return FALSE; /* 获取超级块失败 */
        }

    /* 分配 4KB 缓冲区 */

    buf = fs_new_buf (FSLOGBLK_SZ);

    if (buf == NULL)
        {
        return FALSE;  /* 分配缓冲区失败 */
        }

    /* 获取超级块中位图块开始的块号 */

    bmpblkstart = sblkp->bmpblkstart;

    /* 获取文件系统总共的逻辑存储块个数 */

    allblknbr = sblkp->fsallblknbr;

    /* 检查逻辑块总个数有效性 */

    if (allblknbr >= FSBLKMAX_NBR)
        {
        retstus = FALSE;
        goto return_step; /* 总逻辑块个数异常 */
        }

    /* 把缓冲区中每个字节都置为 FS_LOGBLK_USED (表示已被分配) */

    krl_memset (buf, FS_LOGBLK_USED, FSLOGBLK_SZ);

    /* 
     * 把缓冲区第3个字节和 第FSBLKMAX_NBR字节设置为 FS_LOGBLK_FREE (表示未被分配), 其中
     *  - 第1个字节表示 第1个逻辑块被 超级块 使用
     *  - 第2个字节表示 第2个逻辑块被 位图块 使用
     */

    bmu8p = (u8_t *) buf;

    for (i = 2; i < FSBLKMAX_NBR; i++)
        {
        bmu8p[i] = FS_LOGBLK_FREE;
        }

    /* 把缓冲区中的数据写入到存储介质的第 bmpblkstart 个逻辑存储块中 */

    if (fs_write_to_fsemsto (devp, buf, bmpblkstart) == ERROR)
        {
        retstus = FALSE;
        goto return_step; /* 写入失败 */
        }

    /* 创建位图块成功 */

    retstus = TRUE;

return_step:

    /* 释放缓冲区 */

    fs_delete_buf (buf, FSLOGBLK_SZ);
    return retstus;
    }

/*********************************************************************************
 * 
 * fs_get_bitmapblk - 获取位图块
 * 
 * DESCRIPTION
 */

static u8_t * fs_get_bitmapblk
    (
    device_t * devp
    )
    {
    fssupblk_t * sblkp;
    buf_t        buf;

    /* 获取超级块 */

    sblkp = fs_get_superblk (devp);

    if (sblkp == NULL)
        {
        return NULL; /* 获取超级块失败 */
        }

    /* 分配 4KB 缓冲区 */

    buf = fs_new_buf (FSLOGBLK_SZ);

    if (buf == NULL)
        {
        return NULL; /* 分配缓冲区失败 */
        }

    /* 缓冲区清0 */

    krl_memset (buf, 0, FSLOGBLK_SZ);

    /* 读取 位图块放到缓冲区 */

    if (fs_read_from_fsemsto (devp, buf, sblkp->bmpblkstart) == ERROR)
        {
        fs_delete_buf (buf, FSLOGBLK_SZ);    /* 释放缓冲区 */
        fs_release_superblk (devp, sblkp);    /* 释放超级块 */
        return NULL;                         /* 读取失败 */
        }

    /* 读取成功, 释放超级块, 返回缓冲区地址 */

    fs_release_superblk (devp, sblkp);

    return ((u8_t *) buf);
    }

/*********************************************************************************
 * 
 * fs_release_bitmapblk - 释放位图块
 * 
 * DESCRIPTION
 */

static bool_t fs_release_bitmapblk
    (
    device_t * devp,
    u8_t *     bitmap
    )
    {
    fssupblk_t * sblkp;

    /* 获取超级块 */

    sblkp = fs_get_superblk (devp);

    if (sblkp == NULL)
        {
        krl_system_die ("fs_release_bitmapblk err1\r\n");
        return FALSE; /* 获取超级块失败 */
        }

    /* 将缓冲区中的内容 回写到 位图块所在的 逻辑存储块 */

    if (fs_write_to_fsemsto (devp, (buf_t) bitmap, sblkp->bmpblkstart) == ERROR)
        {
        fs_release_superblk (devp, sblkp);     /* 释放超级块 */
        krl_system_die ("fs_release_bitmapblk err2\r\n");
        return FALSE;                         /* 回写失败 */
        }

    /* 回写成功, 释放超级块和缓存区 */

    fs_release_superblk (devp, sblkp);     /* 释放超级块 */
    fs_delete_buf ((buf_t) bitmap, FSLOGBLK_SZ);     /* 释放缓存区 */

    return TRUE;
    }

/****** 逻辑块相关 (分配空闲/释放占有) ******/

/*********************************************************************************
 * 
 * fs_alloc_freelogblk - 分配新的空闲逻辑存储块
 * 
 * DESCRIPTION
 */

static uint_t fs_alloc_freelogblk
    (
    device_t * devp
    )
    {
    uint_t  blkidx = 0;
    u8_t *  bitmap;
    uint_t  i;

    /* 获得位图块 */

    bitmap = fs_get_bitmapblk (devp);

    if (bitmap == NULL)
        {
        return 0; /* 位图块获得失败, 分配空闲逻辑块失败 */
        }

    /* 在位图数据中找到一个为0的字节就置1, 并返回该字节序号对应的空闲逻辑存储块号 (即被分配了) */

    for (i = 2; i < FSBLKMAX_NBR; i++)
        {
        if (bitmap[i] == FS_LOGBLK_FREE)
            {
            bitmap[i] = FS_LOGBLK_USED; /* 标记该内存块已被使用 */
            blkidx    = i;              /* 分配到的空闲逻辑块号 */
            goto return_step;
            }
        }

    /* 未找到空闲逻辑块 */

    blkidx = 0;

return_step:

    /* 释放位图块, 并返回获得的空闲逻辑块号 */

    fs_release_bitmapblk (devp, bitmap);

    return blkidx;
    }

/*********************************************************************************
 * 
 * fs_free_usedlogblk - 释放已占用的逻辑存储块
 * 
 * DESCRIPTION
 */

static uint_t fs_free_usedlogblk
    (
    device_t * devp,
    uint_t     blkidx
    )
    {
    u8_t *  bitmap;

    /* 检验参数的块号是否合法 */

    if(blkidx > FSBLKMAX_NBR)
        {
        krl_system_die ("fs_free_usedlogblk err\r\n");
        return -1;
        }

    /* 获得位图块 */

    bitmap = fs_get_bitmapblk (devp);

    if (bitmap == NULL)
        {
        return -1; /* 位图块获得失败, 分配空闲逻辑块失败 */
        }
    
    /* 标记该块逻辑块未被使用 */

    bitmap[blkidx] = 0;
    
    /* 释放位图块, 并返回获得的空闲逻辑块号 */

    fs_release_bitmapblk (devp, bitmap);
    
    return 0;
    }

/****** 根目录相关 (创建) ******/

/*********************************************************************************
 * 
 * fs_create_rootdir - 建立根目录
 * 
 * DESCRIPTION
 */

static bool_t fs_create_rootdir
    (
    device_t * devp
    )
    {
    bool_t       retstus;
    fssupblk_t * sblkp;
    buf_t        buf;
    uint_t       blkidx;
    fsobjmh_t *  objmhp;

    /* 获取超级块 */

    sblkp = fs_get_superblk (devp);

    if (sblkp == NULL)
        {
        return FALSE; /* 获取超级块失败 */
        }

    /* 分配 4KB 大小缓冲区 */

    buf = fs_new_buf (FSLOGBLK_SZ);

    if (buf == NULL)
        {
        retstus = FALSE;    /* 分配缓冲区失败 */
        goto return_step2;
        }

    /* 缓冲区清0 */

    krl_memset (buf, 0, FSLOGBLK_SZ);

    /* 分配一个空闲逻辑块 */

    blkidx = fs_alloc_freelogblk (devp);

    if (blkidx <= 0)
        {
        retstus = FALSE;    /* 分配缓冲区失败 */
        goto return_step1;
        }

    /* 初始化超级块中的根目录 */

    sblkp->rootdir.name[0] = '/';              /* 设置根目录名为 '/' */
    sblkp->rootdir.type    = FS_OBJTYPE_DIR;   /* 设置根目录类型为目录类型 */
    sblkp->rootdir.blkidx  = blkidx;  /* 设置根目录的 fsobj_t 结构所在逻辑存储块号为 新分配的 blkidx */

    /* 文件系统对象管理头结构体 设置 */

    objmhp = (fsobjmh_t *) buf;

    fsobjmh_t_init (objmhp);                 /* 初始化 fsobjmh_t 结构 */

    objmhp->type               = FS_MHTYPE_DIR; /* 文件系统对象管理头 类型为 DIR 类型 */
    objmhp->sfblkidx           = blkidx;        /* 对象管理头自身所在的逻辑块序号为新分配的块 */
    objmhp->curwrtblkidx       = blkidx;        /* 正在写入的块, 设置为新分配的块 */
    objmhp->curwrtblkoffset    = 512;           /* 文件数据在将要写入的逻辑块中的偏移 (跳过 fsobjmh_t) */
    objmhp->logblk[0]. blkstart = blkidx;        /* 逻辑存储块管理数组[0]使用的逻辑存储块从 blkidx 开始 */
    objmhp->logblk[0]. blknbr   = 1;             /* 逻辑存储块管理数组[0]使用的连续逻辑存储块个数为 1 */

    /* 把缓冲区中的数据写入新分配的空闲逻辑存储块中 (文件系统对象管理头结构体 子域已设置) */

    if (fs_write_to_fsemsto (devp, buf, blkidx) == ERROR)
        {
        retstus = FALSE;    /* 写入逻辑存储块失败 */
        goto return_step1;
        }

    /* 创建根目录成功 */

    retstus = TRUE;

return_step1:

    /* 释放缓冲区 */

    fs_delete_buf (buf, FSLOGBLK_SZ);

return_step2:

    /* 释放超级块, 并返回创建根目录的结果 */

    fs_release_superblk (devp, sblkp); 

    return retstus;
    }

/* 获取根目录 的 fsobj_t 结构 */

static fsobj_t * fs_get_rootdirstr
    (
    device_t * devp
    )
    {
    fsobj_t *    rdirp;
    fssupblk_t * sblkp;
    buf_t        buf;


    /* 获取超级块 */

    sblkp = fs_get_superblk (devp);

    if (sblkp == NULL)
        {
        return NULL; /* 获取超级块失败 */
        }

    /* 分配一个 fsobj_t 结构体空间 */

    buf = fs_new_buf (sizeof (fsobj_t));

    if (buf == NULL)
        {
        rdirp = NULL;
        goto return_step; /* 分配缓冲区失败 */
        }

    /* 把超级块中的 fsobj_t 复制到 缓冲区 */

    krl_memncpy ((buf_t) &sblkp->rootdir, buf, sizeof (fsobj_t));

    /* 设置缓冲区的首地址为返回地址 */

    rdirp = (fsobj_t *) buf;

return_step:

    /* 返回根目录并释放超级块 */

    fs_release_superblk (devp, sblkp);

    return rdirp;
    }

/* 释放根目录 的 fsobj_t 结构 */

static bool_t fs_release_rootdirstr
    (
    device_t * devp,
    fsobj_t *  rdirp
    )
    {

    /* 释放 fsobj_t 大小的缓冲区 */

    fs_delete_buf ((buf_t) rdirp, sizeof (fsobj_t));

    return TRUE;
    }

/* 获取根目录块 */

static void * fs_get_rootdirblk
    (
    device_t * devp
    )
    {
    void *    rdblkp;
    fsobj_t * rdirp;
    buf_t     buf;

    /* 获取根目录的 fsobj_t 结构体 */

    rdirp = fs_get_rootdirstr (devp);

    if (rdirp == NULL)
        {
        return NULL; /*  获取失败*/
        }

    /* 分配 4KB 缓冲区 */

    buf = fs_new_buf (FSLOGBLK_SZ);

    if (buf == NULL)
        {
        rdblkp = NULL;
        goto return_step2;  /* 分配失败 */
        }

    /* 清空缓冲区 */

    krl_memset (buf, 0, FSLOGBLK_SZ);

    /* 将 根目录所在的 逻辑存储块中的 内容读取到缓冲区中 */

    if (fs_read_from_fsemsto (devp, buf, rdirp->blkidx) == ERROR)
        {
        rdblkp = NULL;
        goto return_step1; /* 读取失败 */
        }

    /* 获取成功 */

    rdblkp = (void *) buf;
    goto return_step2;

return_step1:

    /* 释放缓冲区 */
    
    fs_delete_buf (buf, FSLOGBLK_SZ);

return_step2:

    /* 释放根目录的 fsobj_t 结构体*/

    fs_release_rootdirstr (devp, rdirp);

    return rdblkp;
    }

/* 释放根目录块 */

static bool_t fs_release_rootdirblk
    (
    device_t * devp,
    void *     blkp
    )
    {
    fsobjmh_t * objmhp;

    /* 根目录逻辑存储块的前512B空间中, 保存的就是 fsobjmh_t 结构体 */

    objmhp = (fsobjmh_t *) blkp;

    /* 
     * 把根目录文件回写到存储介质中, 块号为 fsobjmh_t 结构体所在的块号
     * (每个文件系统对象 (文件/目录) 限制只分配一个 fsobjmh_t 结构体, 所以这样操纵可行)
     */

    if (fs_write_to_fsemsto (devp, blkp, objmhp->sfblkidx) == ERROR)
        {
        krl_system_die ("fs_release_rootdirblk err\r\n");
        return FALSE;   /* 写入失败 */
        }

    /* 释放缓冲区 */

    fs_delete_buf (blkp, FSLOGBLK_SZ);

    return TRUE;
    }

/****** 字符串操作相关 (比较/获取长度/复制) ******/

/*********************************************************************************
* 
* fs_strcmp - 比较字符串是否匹配
* 
* DESCRIPTION
* 若 str_s = str_d, 则返回 0; 若 str_s != str_d, 则返回 -1;
*/

sint_t fs_strcmp
    (
    const char_t * str_s,
    const char_t * str_d
    )
    {
    FOREVER
        {
        if (*str_s != *str_d)
            {
            return -1;
            }

        /* 检测字符串是否结束 */

        if (*str_s == EOS)
            {
            break;
            }

        /* 指针偏移 */

        str_s++;
        str_d++;
        }

    return 0;
    }

/* 获取字符串长度 */

uint_t fs_strlen
    (
    const char_t * str_s
    )
    {
    uint_t len = 0;

    while (*str_s++ != EOS)
        {
        len++;
        }

    return len;
    }

/*********************************************************************************
* 
* fs_strcpy - 复制字符串
* 
* DESCRIPTION
*/

uint_t fs_strcpy
    (
    const char_t * str_s,
    char_t *       str_d
    )
    {
    uint_t len = 0;

    /* 复制, 直到源字符串结束 */

    while (*str_s != EOS)
        {
        *str_d++ = *str_s++;
        len++;
        }

    /* 加结束符 */

    *str_d = EOS;

    /* 返回计数变量 */

    return len;
    }

/****** 文件路径名相关 (检查/提取) ******/

/*********************************************************************************
* 
* fs_check_pathname - 检查文件路径名 有效性
* 
* DESCRIPTION
* 检查文件路径名是否是 "/xxx" 的格式
*/

sint_t fs_check_pathname
    (
    const char_t * pname
    )
    {
    uint_t   i;
    const char_t * chp = pname;

    /* 检查文件路径名第一个字符是否为 '/' */

    if (chp[0] != '/')
        {
        return -1;
        }

    /* 遍历检查字符串 */

    i = 1;

    while (i++)
        {
        
        /* 检查除第一个字符外是否还有 '/' */

        if (chp[i] == '/')
            {
            return -1;
            }

        /* 检查文件名是否大于最大允许长度 */

        if (i > FSOBJ_NM_MAX)
            {
            return -1;
            }

        /* 判断文件名字符串是否结束 */

        if ((chp[i] == EOS) && (i > 1))
            {
            break;
            }
        }

    return 0;
    }

/*********************************************************************************
* 
* fs_get_pathname - 提取文件路径名
* 
* DESCRIPTION
*/

sint_t fs_get_pathname
    (
    const char_t * fname,
    char_t *       buf
    )
    {
    sint_t stus;

    /* 检查参数指针有效性 */

    if ((fname == NULL) || (buf == NULL))
        {
        return -1;
        }

    /* 检查文件路径名是不是 "/xxx" 的形式 */

    stus = fs_check_pathname (fname);

    if (stus != 0)
        {
        return -1; /* 文件名非法 */
        }

    /* 拷贝路径名 到 buf (第一个 '/' 除外) */

    fs_strcpy (&fname[1], buf);

    return 0;
    }

/****** 文件存在检查相关 ******/

/*********************************************************************************
* 
* fs_check_filexist - 检查目标对象(文件)是否存在于储存介质上
* 
* DESCRIPTION
* 搜索根目录对象 (块) 中所有的 fsobj_t 结构, 并指定的与目标文件名对比来判断其是否存在于
* 存储介质中.
*/

sint_t fs_check_filexist
    (
    device_t *     devp,
    const char_t * fname
    )
    {
    sint_t      retstus;
    uint_t      len;
    void *      rdblkp;
    fsobjmh_t * objmhp;
    fsobj_t *   rdirp;
    void *      rdirmaxp;

    /* 获得目标文件名 */

    len = fs_strlen (fname);

    /* 检查有目标文件名长度效性 */

    if ((len < 1) || (len > FSOBJ_NM_MAX))
        {
        return -1; /* 文件名长度非法 */
        }

    /* 获取根目录块 */

    rdblkp = fs_get_rootdirblk (devp);

    if (rdblkp == NULL)
        {
        return -1;  /* 获取失败 */
        }

    /* 提取根目录块中的 文件对象管理头 结构体 */

    objmhp = (fsobjmh_t *) rdblkp;

    /* 检查该 fsobjmh_t 结构的类型是不是 FSMH_TYPE_DIR */

    if (objmhp->type != FS_MHTYPE_DIR)
        {
        retstus = -1;
        goto return_step;
        }

    /* 
     * 检查根目录文件是不是为空 (即没写入任何数据):
     *  - 当前写入的逻辑存储块号 == 对象的逻辑存储块管理数组[0]的起始逻辑存储块号;
     *  - 当前写入的逻辑储存块内偏移字节 == 对象的数据内容在第一个逻辑存储块中的偏移字节;
     * 表示根目录下没有对应的文件
     */

    if ((objmhp->curwrtblkidx == objmhp->logblk[0].blkstart) ||
        (objmhp->curwrtblkoffset == objmhp->firstblkoffset))
        {
        retstus = -1;
        goto return_step;  /* 存储介质上不存在根目录外的文件对象 */
        }

    /* 指向根目录文件的第一个字节 */

    rdirp = (fsobj_t *) ((uint_t) objmhp + objmhp->firstblkoffset);

    /* 指向根目录文件的结束地址 */

    rdirmaxp = (void *) ((uint_t) rdblkp + FSLOGBLK_SZ - 1);

    /* 遍历根目录块中的所有 fsobj_t 结构体 */

    while ((void *) rdirp < rdirmaxp)
        {

        /* 
         * 如果这个 fsobj_t 结构的类型是 FS_OBJTYPE_FIL, 说明它对应的是文件而不是目录;
         * 继续比较其文件名
         */

        if (rdirp->type == FS_OBJTYPE_FIL)
            {
            if (fs_strcmp(rdirp->name, fname) == 0)
                {
                retstus = 0;
                goto return_step;  /* 文件名比对成功 */
                }
            }

        /* 指针偏移 */

        rdirp++;
        }

    /* 未找到指定文件名的文件 */

    retstus = -1;

return_step:

    /* 释放根目录块 */

    fs_release_rootdirblk (devp, rdblkp);

    return retstus;
    }

/****** 文件操作相关 (新建/删除/打开/关闭/读取/写入) ******/

/*********************************************************************************
* 
* fs_create_objblk - 新建文件对象函数
* 
* DESCRIPTION
* 1) 分配一个空闲的逻辑存储块
* 2) 在根目录文件的末尾写入这个新建文件对应的 fsobj_t 结构
* 3) 在一个新的4KB大小的缓冲区中初始化新建文件对应的 fsobjmh_t 结构
* 4) 将这个新的4KB大小的缓冲区中的数据写入到之前分配的空闲逻辑存储块中
*/

drvstus_t fs_create_objblk
    (
    device_t *   devp,
    const char * fname,
    uint_t       type,
    uint_t       value
    )
    {
    drvstus_t   retstus;
    uint_t      blkidx;
    buf_t       buf;
    void *      rdblkp;
    fsobjmh_t * rdirmhp;
    fsobj_t *   newobjp;
    fsobjmh_t * newobjmhp;

    /* 检查是不是新建文件 (目前只支持新建文件) */

    if (type != FS_OBJTYPE_FIL)
        {
        return ERROR;
        }

    /* 分配一个 4KB 缓冲区 */

    buf = fs_new_buf (FSLOGBLK_SZ);

    if (buf == NULL)
        {
        return ERROR;  /* 分配缓冲区失败 */
        }

    /* 清0缓冲区 */

    krl_memset (buf, 0, FSLOGBLK_SZ);

    /* 分配一个空闲的逻辑存储块 */

    blkidx = fs_alloc_freelogblk (devp);

    if (blkidx <= 0)
        {
        retstus = ERROR;
        goto return_step2; /* 分配空闲逻辑存储块失败 */
        }

    /* 获得根目录块 */

    rdblkp = fs_get_rootdirblk (devp);

    if (rdblkp == NULL)
        {
        retstus = ERROR;
        goto return_step2; /* 获得根目录块失败 */
        }

    /* 提取出文件对象管理头结构体 */

    rdirmhp = (fsobjmh_t *) rdblkp;

    /* 指向文件对象的当前写入地址 */

    newobjp = (fsobj_t *) ((uint_t) rdblkp + rdirmhp->curwrtblkoffset);

    /* 检查文件当前写入地址有效性 */

    if ((uint_t) newobjp >= ((uint_t) rdblkp + FSLOGBLK_SZ))
        {
        retstus = ERROR;
        goto return_step1; /* 当前文件写入地址非法 */
        }

    /* 设置 新的 文件对象的 fsobj_t 结构体 */

    newobjp->status = 0;              /* 状态设置为 0 */
    newobjp->type   = type;           /* 设置为指定类型 */
    newobjp->blkidx = blkidx;         /* 设置使用的逻辑存储块号 */
    fs_strcpy (fname, newobjp->name); /* 设置对象名 */

    /* 更改根目录数据 */

    rdirmhp->size            += (uint_t) (sizeof (fsobj_t)); /* 增加根目录大小 */
    rdirmhp->curwrtblkoffset += (uint_t) (sizeof (fsobj_t)); /* 调整当前写入块偏移值 */

    /* 构建 新的文件对象的 fsobjmh_t 结构体 */

    newobjmhp = (fsobjmh_t *) buf;                  /* 指向新分配的缓冲区 */

    fsobjmh_t_init (newobjmhp);                     /* 初始化 fsobjmh_t 结构体 */
    newobjmhp->type               = FS_MHTYPE_FIL;  /* 文件管理头类型为 文件类型 */
    newobjmhp->sfblkidx           = blkidx;         /* 文件管理头所在逻辑块号 */
    newobjmhp->curwrtblkidx       = blkidx;         /* 当前写入块号 */
    newobjmhp->curwrtblkoffset    = 512;            /* 当前写入块的写入偏移量设为 512B */
    newobjmhp->logblk[0].blkstart = blkidx;         /* 逻辑块管理数组[0]记录的起始逻辑块号 */
    newobjmhp->logblk[0].blknbr   = 1;              /* 使用的连续逻辑块数量 */

    /* 把缓冲区中的数据写入新分配的逻辑存储块中 */

    if (fs_write_to_fsemsto (devp, buf, blkidx) == ERROR)
        {
        retstus = ERROR;
        goto return_step1; /* 缓冲区数据写入逻辑存储块失败 */
        }

    /* 创建新文件成功 */

    retstus = OK;

    /* 函数返回 */

return_step1:

    /* 释放根目录 */

    fs_release_rootdirblk (devp, rdblkp);

return_step2:

    /* 释放 4KB 缓冲区 */

    fs_delete_buf (buf, FSLOGBLK_SZ);

    return retstus;
    }

/*********************************************************************************
* 
* fs_create_file - 新建文件接口函数
* 
* DESCRIPTION
* 新建一个文件:
* 1) 从文件路径名中提取存文件名
* 2) 检查存储介质上是否已经存在这个文件
* 3) 调用实际创建文件的函数
*/

drvstus_t fs_create_file
    (
    device_t *     devp,
    const char_t * fname,
    uint_t         flag
    )
    {
    drvstus_t retstus;

    /* 定义一个字符缓冲区 */

    char_t fnm[FSOBJ_NM_MAX] = {0};

    /* 从文件路径中提取出纯文件名 */

    if (fs_get_pathname (fname, fnm) != 0)
        {
        return ERROR;   /* 指定的文件名非法 */
        }

    /* 检查存储介质上是否已经存在这个文件 */

    if (fs_check_filexist (devp, fname) != 0)
        {
        return ERROR;   /* 存储介质上没有找到该名字的文件 */
        }

    /* 调用实际创建文件的函数 */

    retstus = fs_create_objblk (devp, fnm, FS_OBJTYPE_FIL, 0);

    return retstus;
    }

/*********************************************************************************
* 
* fs_delete_objblk - 删除文件块
* 
* DESCRIPTION
* 1) 获取根目录文件
* 2) 从根目录文件中查找将要删除的文件 fsobj_t 结构
* 3) 释放该文件占用的逻辑存储块, 初始化该文件对应的 fsobj_t (并设置其类型为 FS_OBJTYPE_DEL)
* 4) 释放根目录文件
*/

sint_t fs_delete_objblk 
    (
    device_t *   devp,
    const char * fname,
    uint_t       type,
    uint_t       value
    ) 
    {
    sint_t      retstus;
    void *      rdblkp;
    fsobjmh_t * rdirmhp;
    void *      rdirmaxp;
    fsobj_t *   delobjp;

    /* 获取根目录文件块 */

    rdblkp = fs_get_rootdirblk (devp);

    if (rdblkp == NULL)
        {
        return -1; /* 获取根目录块失败 */
        }

    /* 获取 根目录块的管理头结构体 */

    rdirmhp = (fsobjmh_t *) rdblkp;

    /* 检查根目录块的类型是否是文件夹类型 */

    if (rdirmhp->type != FS_MHTYPE_DIR)
        {
        retstus = -1;
        goto return_step;   /* 根目录块的类型非法 */
        }

    /* 检查根目录文件中是否有数据 */

    if ((rdirmhp->curwrtblkidx == rdirmhp->logblk[0].blkstart) &&
        (rdirmhp->curwrtblkoffset == rdirmhp->firstblkoffset))
        {
        retstus = -1;
        goto return_step;   /* 根目录块中没有数据 */
        }

    /* 指向根目录文件的第一个字节 */

    delobjp = (fsobj_t *) ((uint_t) rdirmhp + rdirmhp->firstblkoffset);

    /* 指向根目录文件的结束地址 */

    rdirmaxp = (void *) ((uint_t) rdblkp + FSLOGBLK_SZ - 1);

    /* 遍历根目录块中的所有 fsobj_t 结构体 */

    while ((void *) delobjp < rdirmaxp)
        {

        /* 
         * 如果这个 fsobj_t 结构的类型是 FS_OBJTYPE_FIL, 说明它对应的是文件而不是目录;
         * 继续比较其文件名
         */

        if (delobjp->type == FS_OBJTYPE_FIL)
            {
            
            /* 找出指定删除的文件名 */

            if (fs_strcmp(delobjp->name, fname) == 0)
                {
                
                /* 释放 fsobj_t 结构的 blkidx 域中的逻辑存储块 */

                fs_free_usedlogblk (devp, delobjp->blkidx);

                /* 初始化 fsobj_t 结构 (清除其中的数据) */

                fsobj_t_init (delobjp);

                /* 设置 fsobj_t 结构 为删除类型 */

                delobjp->type = FS_OBJTYPE_DEL;

                retstus = 0;
                goto return_step;
                }
            }

        /* 指针偏移 */

        delobjp++;
        }

    /* 未在存储介质中找到该文件, 删除失败 */

    retstus = -1;

return_step:

    /* 释放根目录文件块 */

    fs_release_rootdirblk (devp, rdblkp);

    return retstus;
    }

/*********************************************************************************
* 
* fs_delete_file - 删除文件接口函数
* 
* DESCRIPTION
* 1) 从文件路径中提取纯文件名
* 2) 调用删除文件核心函数
*/

drvstus_t fs_delete_file
    (
    device_t *     devp,
    const char_t * fname,
    uint_t         flag
    )
    {

    char fnm[FSOBJ_NM_MAX] = {0};

    /* 检查 flag 有效性 */

    if (flag != 0)
        {
        return ERROR;
        }

    /* 提取纯文件名 */

    if (fs_get_pathname (fname, fnm) != 0)
        {
        return ERROR; /* 文件名提取失败 */
        }

    /* 调用删除文件的核心函数 */

    if (fs_delete_objblk (devp, fnm, FS_OBJTYPE_FIL, 0) != 0)
        {
        return ERROR;   /* 删除成功 */
        }

    return OK;
    }

/*********************************************************************************
* 
* fs_open_objblk - 打开文件核心函数
* 
* DESCRIPTION
* 1) 从文件路径名中提取文件名
* 2) 获取根目录文件
* 3) 在根目录文件中搜索该文件对应的 fsobj_t 结构
* 4) 分配一个4KB缓冲区
* 5) 读取该文件对应的 fsobj_t 结构的 blknbr 域中指向的逻辑存储块到缓冲区中
* 6) 获得该缓冲区的所指的逻辑存储块的 fsobjmh_t 结构体
* 7) 释放问目录文件
* 8) 返回获得的 fsobjmh_t 结构体
*/

fsobjmh_t * fs_open_objblk
    (
    device_t *     devp,
    const char_t * fname
    )
    {
    fsobj_t *   rdblkp;
    void *      rdirmaxp;
    fsobj_t *   opnobjp;
    fsobjmh_t * rdirmhp;
    fsobjmh_t * objmhp;
    fsobjmh_t * retobjmhp;
    char_t      fnm[FSOBJ_NM_MAX] = {0};
    buf_t       buf;  

    /* 从文件路径名中提取 纯文件名 */

    if (fs_get_pathname (fname, fnm) != 0)
        {
        return NULL;
        }

    /* 获取根目录文件 */

    rdblkp = fs_get_rootdirblk (devp);
    
    if (rdblkp == NULL)
        {
        return NULL; /* 获取根目录文件失败 */
        }

    /* 提取 根目录文件中 fsobjmh_t 结构 */

    rdirmhp = (fsobjmh_t *) rdblkp;

    /* 判断根目录文件的类型是否有效 */

    if (rdirmhp->type != FS_MHTYPE_DIR)
        {
        retobjmhp = NULL;
        goto return_step2;
        }

    /* 判断根目录文件中是否有数据 */

    if ((rdirmhp->curwrtblkidx == rdirmhp->logblk[0].blkstart) &&
        (rdirmhp->curwrtblkoffset == rdirmhp->firstblkoffset))
        {
        retobjmhp = NULL;
        goto return_step2;
        }

    /* 指向根目录文件的第一个字节 */

    opnobjp = (fsobj_t *) ((uint_t) rdirmhp + rdirmhp->firstblkoffset);

    /* 指向根目录文件的结束地址 */

    rdirmaxp = (void *) ((uint_t) rdblkp + FSLOGBLK_SZ - 1);

    /* 遍历根目录块中的所有 fsobj_t 结构体 */

    while ((void *) opnobjp < rdirmaxp)
        {

        /* 
         * 如果这个 fsobj_t 结构的类型是 FS_OBJTYPE_FIL, 说明它对应的是文件而不是目录;
         * 继续比较其文件名
         */

        if (opnobjp->type == FS_OBJTYPE_FIL)
            {
            
            /* 找出指定打开的文件名 */

            if (fs_strcmp(opnobjp->name, fname) == 0)
                {
                goto return_objmh; /* 找到要打开的文件, 提取 fsobjmh_t 信息 */
                }
            }

        /* 指针偏移 */

        opnobjp++;
        }

    /* 未找到指定文件名的 fsobj_t */

    retobjmhp = NULL;
    goto return_step2;

return_objmh:

    /* 分配 4KB 大小的缓冲区 */

    buf = fs_new_buf (FSLOGBLK_SZ);

    if (buf == NULL)
        {
        retobjmhp = NULL;
        goto return_step2;  /* 分配缓冲区失败 */
        }

    /* 读取该文件占用的逻辑储存块 */

    if (fs_read_from_fsemsto (devp, buf, opnobjp->blkidx) == ERROR)
        {
        retobjmhp = NULL;
        goto return_step1;  /* 读取存储块失败 */
        }

    /* 提取找到的逻辑存储块的 fsobjmh_t 结构体 */

    objmhp = (fsobjmh_t *) buf;

    /* 检验 objmhp 子域有效性 */

    if ((objmhp->type != FS_OBJTYPE_FIL) || (objmhp->firstblkoffset != 512))
        {
        retobjmhp = NULL;
        goto return_step1;  /* objmhp 子域 检验失败 */
        }

    /* 获取指定的文件的文件管理头成功 */

    retobjmhp = objmhp;
    goto return_step2;

return_step1:

    /* 释放 4KB 缓冲区 */

    fs_delete_buf (buf, FSLOGBLK_SZ);

return_step2:

    /* 释放根目录文件 */

    fs_release_rootdirblk (devp, rdblkp);

    return retobjmhp;
    }

/*********************************************************************************
* 
* fs_open_file - 打开文件接口函数
* 
* DESCRIPTION
* 1) 检查IO包中的文件路径名
* 2) 调用打开文件的核心函数
* 3) 把缓冲区中的 fsobjmh_t 结构的地址保存到 IO 包的 fnode 域
*/

drvstus_t fs_open_file
    (
    device_t *  devp,
    void *      iopack
    )
    {
    objnode_t * obnodep = (objnode_t *) iopack;
    fsobjmh_t * objmhp;

    /* 检查 IO 包中的路径名 */

    if (obnodep->fname == NULL)
        {
        return ERROR; /* 未指定路径名 */
        }
    
    /* 调用打开文件的核心函数 */

    objmhp = fs_open_objblk (devp, (char_t *) obnodep->fname);

    if (objmhp == NULL)
        {
        return ERROR; /* 打开文件失败 */
        }

    /* 把返回的 fsobjmh_t 赋值给 IO 包的 fnode 域 */

    obnodep->fnode = (void *) objmhp;

    return OK;
    }

/* 关闭文件核心函数 */

drvstus_t fs_close_objblk
    (
    device_t * devp,
    void *     objblkp
    )
    {
    fsobjmh_t * objmhp;

    /* I/O包指针 */

    objmhp = (fsobjmh_t *) objblkp;

    /* 将缓冲区中的数据回写到逻辑存储块 (数据同步) */

    if (fs_write_to_fsemsto (devp, objblkp, objmhp->sfblkidx) == ERROR)
        {
        return ERROR; /* 写入失败 */
        }
    
    /* 释放缓冲区 */

    fs_delete_buf (objblkp, FSLOGBLK_SZ);
    
    return OK;
    }

/*********************************************************************************
* 
* fs_close_file - 关闭文件接口函数
* 
* DESCRIPTION
* 创建指定名字和先关属性的一个文件
*/

drvstus_t fs_close_file
    (
    device_t * devp,
    void *     iopack
    )
    {
    objnode_t * objndp;
    drvstus_t   retstus;

    /* I/O包指针 */

    objndp = (objnode_t *) iopack;

    /* 检查文件是否已经打开 */

    if (objndp->fnode == NULL)
        {
        return ERROR; /* 检验失败 */
        }

    /* 调用关闭文件核心函数 */

    retstus = fs_close_objblk (devp, objndp->fnode);

    return retstus;
    }

/*********************************************************************************
* 
* fs_read_objblk - 读取文件核心函数
* 
* DESCRIPTION
* 1) 检验 要读文件的 fsobjmh_t 结构子域有效性
* 2) 校验 要读取得最大长度
* 3) 将逻辑块中的数据起始地址的数据读取到 缓冲区中 (参数buf)
*/

drvstus_t fs_read_objblk 
    (
    device_t *  devp,
    fsobjmh_t * objmhp, 
    buf_t       buf, 
    uint_t      len
    )
    {
    void * readp;

    /* 检查文件相关信息有效性 */

    if ((objmhp->sfblkidx != objmhp->curwrtblkidx) || 
        (objmhp->curwrtblkidx != objmhp->logblk[0].blkstart))
        {
        return ERROR;
        }

    /* 文件读取数据长度是否超过最大长度 (4096 - 512) */

    if (len > (FSLOGBLK_SZ - objmhp->firstblkoffset))
        {
        return ERROR;
        }

    /* 获取读取位置的起始地址 */

    readp = (void *) ((uint_t) objmhp + objmhp->firstblkoffset);

    /* 将该起始地址的数据读取到 buf 中 */

    krl_memncpy (readp, buf, len);

    return OK;
    }

/*********************************************************************************
* 
* fs_read_file - 读取文件接口函数
* 
* DESCRIPTION
* 1) 检验 文件是否打开, objnode_t 的 buf缓冲区 和 大小 是否有效
* 2) 调用读取文件数据的核心函数
*/

drvstus_t fs_read_file
    (
    device_t * devp,
    void *     iopack
    )
    {
    objnode_t * objndp;
    drvstus_t   retstus;

    /* I/O包指针 */

    objndp = (objnode_t *) iopack;

    /* 检查文件是否已经打开, 存放文件数据的缓冲区和大小是否有效 */

    if ((objndp->fnode == NULL) || (objndp->buf == NULL) || (objndp->bufsz != FSLOGBLK_SZ))
        {
        return ERROR; /* 检验失败 */
        }

    /* 调用读取数据核心函数 */

    retstus = fs_read_objblk (devp, (fsobjmh_t *) objndp->fnode, objndp->buf, objndp->len);

    return retstus;
    }

/* 写入文件数据的核心函数 */

drvstus_t fs_write_objblk 
    (
    device_t *  devp,
    fsobjmh_t * objmhp,
    buf_t       buf,
    uint_t      len
    )
    {
    void *    writep;
    drvstus_t retstus;

    /* 检查文件相关信息有效性 */

    if ((objmhp->sfblkidx != objmhp->curwrtblkidx) || 
        (objmhp->curwrtblkidx != objmhp->logblk[0].blkstart))
        {
        return ERROR;
        }

    /* 文件写入数据长度是否超过最大长度 (4096 - 512) */

    if ((objmhp->firstblkoffset + len) > FSLOGBLK_SZ)
        {
        return ERROR;
        }

    /* 获取写入位置的起始地址 */

    writep = (void *) ((uint_t) objmhp + objmhp->firstblkoffset);

    /* 将该起始地址的数据读取到 buf 中 */

    krl_memncpy (buf, writep, len);

    /* 增加文件大小 */

    objmhp->size += len;

    /* 偏移下次写入位置 */

    objmhp->curwrtblkoffset += len;

    /* 将数据写入逻辑存储块 */

    if (fs_write_to_fsemsto (devp, (void *) objmhp, objmhp->curwrtblkidx) == ERROR)
        {
        retstus = ERROR;
        goto error_step;
        }

    /* 数据写入成功 */

    retstus = OK;
    goto return_step;

    /* 错误处理 */

error_step:

    objmhp->size            -= len;
    objmhp->curwrtblkoffset -= len;

    /* 函数返回 */

return_step:

    return retstus;
    }

/*********************************************************************************
* 
* fs_write_file - 改写文件接口函数
* 
* DESCRIPTION
* 创建指定名字和先关属性的一个文件
*/

drvstus_t fs_write_file
    (
    device_t * devp,
    void *     iopack
    )
    {
    objnode_t * objndp;
    drvstus_t   retstus;

    /* I/O包指针 */

    objndp = (objnode_t *) iopack;

    /* 检查文件是否已经打开, 存放文件数据的缓冲区和大小是否有效 */

    if ((objndp->fnode == NULL) || (objndp->buf == NULL) || (objndp->bufsz != FSLOGBLK_SZ))
        {
        return ERROR; /* 检验失败 */
        }
    
    /* 调用写入数据核心函数 */

    retstus = fs_write_objblk (devp, (fsobjmh_t *) objndp->fnode, objndp->buf, objndp->len);

    return retstus;
    }

/* =================== 硬件相关 =================== */

/*********************************************************************************
* 
* drv_ramfs_init - 文件系统初始化
* 
* DESCRIPTION
*/

static void drv_ramfs_init
    (
    device_t * devp
    )
    {
    
    /* 建立超级块 */

    if (fs_create_superblk (devp) == FALSE)
        {
        krl_system_die ("drv_ramfs_init: create_superblk err\r\n");
        return;   /* 建立超级块失败 */
        }

    /* 建立位图块 */

    if (fs_create_bitmap (devp) == FALSE)
        {
        krl_system_die ("drv_ramfs_init: create_bitmap err\r\n");
        return;   /* 建立位图块失败 */
        }

    /* 建立根目录 */

    if (fs_create_rootdir (devp) == FALSE)
        {
        krl_system_die ("drv_ramfs_init: create_rootdir err\r\n");
        return;   /* 建立根目录失败 */
        }

    return;
    }

/* =================== 中断服务函数 =================== */

/* NONE */

/* =================== IO 分发函数 =================== */

/*********************************************************************************
 * 
 * drv_ramfs_open - ramfs 设备驱动程序的打开函数 
 * 
 * DESCRIPTION
 * 因为设备驱动程序没有对应新建文件的功能派发函数, 所以就给IO包的访问标志域设置
 * 不同的编码, 来进行判断 (两个宏是由驱动模型规定的).
 */

static drvstus_t drv_ramfs_open
    (
    device_t * devp,
    void *     iopack
    )
    {
    objnode_t * objndp;
    drvstus_t   retstus;

    /* I/O包指针 */

    objndp = (objnode_t *) iopack;

    /* 判断 IO 包的访问标志 */

    if (objndp->acsflag == FSDEV_OPFLG_OPNFILE)
        {
        retstus = fs_open_file (devp, iopack);
        return retstus;
        }
    else if (objndp->acsflag == FSDEV_OPFLG_NEWFILE)
        {
        retstus = fs_create_file (devp, objndp->fname, 0);
        return retstus;
        }

    /* 校验 访问标识失败 */

    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_ramfs_close - ramfs 设备驱动程序关闭函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_ramfs_close
    (
    device_t * devp,
    void *     iopack
    )
    {
    drvstus_t retstus;

    retstus = fs_close_file (devp, iopack);

    return retstus;
    }

/*********************************************************************************
 * 
 * drv_ramfs_read - ramfs 设备驱动程序读函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_ramfs_read
    (
    device_t * devp,
    void *     iopack
    )
    {
    drvstus_t retstus;

    retstus = fs_read_file (devp, iopack);

    return retstus;
    }

/*********************************************************************************
* 
* drv_ramfs_write - ramfs 设备驱动程序写入函数
* 
* DESCRIPTION
*/

static drvstus_t drv_ramfs_write
    (
    device_t * devp,
    void *     iopack
    )
    {
    drvstus_t retstus;

    retstus = fs_write_file (devp, iopack);

    return retstus;
    }

/*********************************************************************************
* 
* drv_ramfs_lseek - ramfs 设备驱动程序调整读写位置函数
* 
* DESCRIPTION
*/

static drvstus_t drv_ramfs_lseek
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
* 
* drv_ramfs_ioctl - ramfs 设备驱动程序控制函数
* 
* DESCRIPTION
*/

static drvstus_t drv_ramfs_ioctl
    (
    device_t * devp,
    void *     iopack
    )
    {
    objnode_t * objndp;
    drvstus_t   retstus;

    /* I/O包指针 */

    objndp = (objnode_t *) iopack;

    /* 根据IO包的控制码进行判断 */

    switch (objndp->ioctlcmd)
        {
        case FSDEV_IOCTL_DELFILE:
            {
            
            /* 删除文件操作的接口函数 */

            retstus = fs_delete_file (devp, objndp->fname, 0);

            } break;

        default:
            retstus = ERROR;
            break;
        }

    return retstus;
    }

/*********************************************************************************
* 
* drv_ramfs_start - ramfs 设备驱动程序开始函数
* 
* DESCRIPTION
*/

static drvstus_t drv_ramfs_start
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
* 
* drv_ramfs_stop - ramfs 设备驱动程序停止函数
* 
* DESCRIPTION
*/

static drvstus_t drv_ramfs_stop
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
* 
* drv_ramfs_powerset - ramfs 设备驱动程序的设置电源函数
* 
* DESCRIPTION
*/

static drvstus_t drv_ramfs_powerset
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
* 
* drv_ramfs_enumdev - ramfs 设备驱动程序枚举设备函数
* 
* DESCRIPTION
*/

static drvstus_t drv_ramfs_enumdev
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
* 
* drv_ramfs_flush - ramfs 设备驱动程序刷新缓存函数
* 
* DESCRIPTION
*/

static drvstus_t drv_ramfs_flush
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
* 
* drv_ramfs_shutdown - ramfs 设备驱动程序关机函数
* 
* DESCRIPTION
*/

static drvstus_t drv_ramfs_shutdown
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }


/* =================== 设置相关结构体的域 =================== */

/*********************************************************************************
* 
* drv_ramfs_set_driver - 填写 driver_t 结构示例变量的相关域
* 
* DESCRIPTION
*/

static void drv_ramfs_set_driver
    (
    driver_t * drvp
    )
    {
    
    /* 设置 I/O 功能分发函数 */

    drvp->dipfunc[IOIF_CODE_OPEN]     = drv_ramfs_open;
    drvp->dipfunc[IOIF_CODE_CLOSE]    = drv_ramfs_close;
    drvp->dipfunc[IOIF_CODE_READ]     = drv_ramfs_read;
    drvp->dipfunc[IOIF_CODE_WRITE]    = drv_ramfs_write;
    drvp->dipfunc[IOIF_CODE_LSEEK]    = drv_ramfs_lseek;
    drvp->dipfunc[IOIF_CODE_IOCTL]    = drv_ramfs_ioctl;
    drvp->dipfunc[IOIF_CODE_START]    = drv_ramfs_start;
    drvp->dipfunc[IOIF_CODE_STOP]     = drv_ramfs_stop;
    drvp->dipfunc[IOIF_CODE_POWERSET] = drv_ramfs_powerset;
    drvp->dipfunc[IOIF_CODE_ENUMDEV]  = drv_ramfs_enumdev;
    drvp->dipfunc[IOIF_CODE_FLUSH]    = drv_ramfs_flush;
    drvp->dipfunc[IOIF_CODE_SHUTDOWN] = drv_ramfs_shutdown;

    /* 设置驱动名 */

    drvp->name = "ramfs_drv";

    return;
    }

/*********************************************************************************
* 
* drv_ramfs_set_device - 填写 device_t 结构示例变量的相关域
* 
* DESCRIPTION
*/

static void drv_ramfs_set_device
    (
    device_t * devp,
    driver_t * drvp
    )
    {

    /* 填写设备标志, 独占使用设备 */

    devp->flag = DEV_ATTRFLG_SHARE;

    /* 填写设备状态 (普通状态, 设备可用) */

    devp->status = DEV_ATTRSTS_NORMAL;

    /* 填写设备类型 (主设备号, 次设备号) */

    devp->id.majtype = DEVICE_CLASSITY_FILESYS; /* filesys 类型设备 */
    devp->id.subtype = 0;                       /* 0 */

    /* 填写设备序号 */

    devp->id.index = 0;                         /* 0 */

    /* 填写设备名 */

    devp->name = "ramfs";

    return;
    }

/* =================== 驱动程序框架 =================== */

/*********************************************************************************
* 
* drv_ramfs_entry - ramfs 设备驱动程序入口函数
* 
* DESCRIPTION
*/

drvstus_t drv_ramfs_entry
    (
    driver_t * drvp,
    uint_t     value,
    void *     param
    )
    {

    /* 判断参数有效性 */

    if (drvp == NULL)
        {
        return ERROR;
        }

    /* 创建 device_t 结构的实例变量 */

    device_t * devp = dev_create_devicedsc ();

    if (devp == NULL)
        {
        return ERROR;
        }

    /* 填写 driver_t 和 device_t 的域 */

    drv_ramfs_set_driver (drvp);
    drv_ramfs_set_device (devp, drvp);

    /* 分配模拟存储介质的内存空间 */

    if (fs_create_fsemsto_mmblk (devp, FSEMSTOBLK_SZ) == ERROR)
        {

        /* 分配模拟存储内存空间失败, 释放资源 (删除设备数据结构的实例变量) */

        goto return_step;
        }

    /* 将设备添加进驱动管理链表 */

    if (dev_add_device_to_driver (devp, drvp) == ERROR)
        {
        
        /* 设备加入驱动失败, 释放资源 (删除设备数据结构的实例变量) */

        goto return_step;
        }

    /* 将设备注册进内核系统 */

    if (krl_dev_register_device (devp) ==  ERROR)
        {

        /* 设备注册进内核失败, 释放资源 (删除设备数据结构的实例变量) */

        goto return_step;
        }

    /* 初始化文件系统 */

    drv_ramfs_init (devp);

    return OK;

return_step:

    /* 删除设备数据结构的实例变量 */

    if (dev_delete_devicedsc (devp) == FALSE)
        {
        return ERROR; /* 删除失败 */
        }

    return ERROR;     /* 返回失败 */
    }

/*********************************************************************************
* 
* drv_ramfs_exit - ramfs 设备驱动程序出口函数
* 
* DESCRIPTION
*/

drvstus_t drv_ramfs_exit
    (
    driver_t * drvp,
    uint_t     value,
    void *     param
    )
    {
    return ERROR;
    }

